package com.yfqy.app.security.login;

import com.yfqy.app.constant.GeneralConstants;
import com.yfqy.app.domain.vo.ResultVO;
import com.yfqy.app.enums.ErrorCode;
import com.yfqy.app.exception.BusinessException;
import com.yfqy.app.service.JwtService;
import com.yfqy.app.util.JSON;
import com.yfqy.app.util.TimeTool;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AbstractAuthenticationTargetUrlRequestHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Author: 梁二东
 * @Date: 2025/5/6 16:37
 * @Description:
 **/
@Component
public class LoginSuccessHandler extends
        AbstractAuthenticationTargetUrlRequestHandler implements AuthenticationSuccessHandler {

    @Autowired
    private JwtService jwtService;

    public LoginSuccessHandler() {
        this.setRedirectStrategy(new RedirectStrategy() {
            @Override
            public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
                    throws IOException {
                // 更改重定向策略，前后端分离项目，后端使用RestFul风格，无需做重定向
                // Do nothing, no redirects in REST
            }
        });
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        Object principal = authentication.getPrincipal();
        if (!(principal instanceof LoginUserInfo currentUser)) {
            throw new BusinessException(ErrorCode.BAD_REQUEST.getCode(), "登陆认证成功后，authentication.getPrincipal()返回的Object对象必须是：UserLoginInfo！");
        }

        currentUser.setSessionId(UUID.randomUUID().toString());

        // 生成token和refreshToken
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("token", generateToken(currentUser));
        responseData.put("userInfo", currentUser);

        // 一些特殊的登录参数。比如三方登录，需要额外返回一个字段是否需要跳转的绑定已有账号页面
        Object details = authentication.getDetails();
        if (details instanceof Map) {
            Map detailsMap = (Map) details;
            responseData.putAll(detailsMap);
        }

        // 虽然APPLICATION_JSON_UTF8_VALUE过时了，但也要用。因为Postman工具不声明utf-8编码就会出现乱码
        response.setContentType(GeneralConstants.CHARSET_UTF8);
        PrintWriter writer = response.getWriter();
        writer.print(JSON.stringify(ResultVO.data(responseData, "登录成功！")));
        writer.flush();
        writer.close();
    }

    public String generateToken(LoginUserInfo currentUser) {
        // 10分钟后过期
        // long expiredTime = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10);
        // 15日后上午8点过期
        long expiredTime = System.currentTimeMillis() + TimeTool.getMillisUntil15DaysLater8AM();
        currentUser.setExpiredTime(expiredTime);
        return jwtService.createJwt(currentUser, expiredTime);
    }

    private String generateRefreshToken(LoginUserInfo loginInfo) {
        return jwtService.createJwt(loginInfo, System.currentTimeMillis() + TimeUnit.DAYS.toMillis(29));
    }
}
